/**
 * Copyright &copy; 2013-2015 山东易科德软件有限公司 All rights reserved.
 */
package cn.net.ecode.common.service;

import java.util.List;

import javax.validation.ValidationException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import cn.net.ecode.common.persistence.DataEntity;
import cn.net.ecode.common.persistence.Page;
import cn.net.ecode.common.persistence.QueryDao;
import cn.net.ecode.common.utils.Reflections;
import cn.net.ecode.common.utils.StringUtils;

/**
 * Service基类
 * @author ThinkGem
 * @version 2014-8-19
 */
@Transactional(readOnly = true)
public abstract class QueryService<D extends QueryDao<T>, T extends DataEntity<?>> extends BaseService {
	
	/**
	 * 持久层对象
	 */
	@Autowired
	protected D dao;

	/**
	 * 实体类类型
	 */
	@SuppressWarnings("unchecked")
	protected Class<T> entityClass = Reflections.getClassGenricType(getClass(), 1);

	/**
	 * 新建实体对象
	 * @return
	 */
	protected T newEntity(){
		T e = null;
		try {
			e = entityClass.newInstance();
		} catch (Exception ex) {
			throw new ServiceException(ex);
		}
		return e;
	}
	
	/**
	 * 获取单条数据
	 * @param id 主键
	 * @return
	 */
	public T get(String id) {
		T entity = null;
		try {
			entity = entityClass.getConstructor(String.class).newInstance(id);
		} catch (Exception e) {
			throw new ServiceException(e);
		}
		return get(entity);
	}
	
	/**
	 * 获取单条数据
	 * @param entity
	 * @return
	 */
	public T get(T entity) {
		return dao.get(entity);
	}

	/**
	 * 获取单条数据，如果获取不到，则实例化一个空实体
	 * @param id 主键编号
	 * @param isNewRecord 如果是新记录，则验证主键编号是否存在。
	 * 					     如果存在抛出ValidationException异常。
	 * @return
	 */
	public T get(String id, boolean isNewRecord) {
		return get(new Class<?>[]{String.class}, new Object[]{id}, isNewRecord);
	}
	
	/**
	 * 获取单条数据，如果获取不到，则实例化一个空实体
	 * @param pk 符合主键数组
	 * @param isNewRecord 如果是新记录，则验证主键编号是否存在。
	 * 					     如果存在抛出ValidationException异常。
	 * @return
	 */
	public T get(Class<?>[] pkClass, Object[] pkValue, boolean isNewRecord) {
		T entity = null;
		if (pkClass != null && pkValue != null && pkClass.length == pkValue.length){
			// 判断是有主键参数值
			boolean paramIsNotBlank = false;
			for(int i = 0; i < pkValue.length; i++){
				if (pkValue[i] != null){
					if (pkValue[i] instanceof String){
						if (StringUtils.isNotBlank((String)pkValue[i])){
							paramIsNotBlank = true;
						}
					}else{
						paramIsNotBlank = true;
					}
				}
			}
			// 如果有主键参数，则查询数据
			if (paramIsNotBlank){
				try {
					entity = entityClass.getConstructor(pkClass).newInstance(pkValue);
				} catch (Exception e) {
					throw new ServiceException(e);
				}
				entity = get(entity);
				// 如果是新记录，并且查询到了数据，则抛出主键已存在异常
				if(isNewRecord && entity != null){
					throw getValidationIdExistsException();
				}
			}
		}
		// 如果仍然没有数据，则new一个新的
		if (entity == null){
			try {
				entity = entityClass.newInstance();
			} catch (Exception e) {
				throw new ServiceException(e);
			}
		}
		return entity;
	}
	
	/**
	 * 查询列表数据
	 * @param entity
	 * @return
	 */
	public List<T> findList(T entity) {
		return dao.findList(entity);
	}
	
	/**
	 * 查询分页数据
	 * @param page 分页对象
	 * @param entity
	 * @return
	 */
	public Page<T> findPage(Page<T> page, T entity) {
		try {
			entityClass.getMethod("setPage", Page.class).invoke(entity, page);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		page.setList(dao.findList(entity));
		return page;
	}
	
	/**
	 * 查询全部列表数据
	 * @param entity
	 * @return
	 */
	public List<T> findAllList(T entity) {
		return dao.findAllList(entity);
	}

	/**
	 * 获取编号存在异常类
	 */
	public static ValidationException getValidationIdExistsException(){
		return getValidationException("编码已存在");
	}

	/**
	 * 获取数据验证异常类
	 */
	public static ValidationException getValidationException(String message){
		return new ValidationException(message);
	}
	
}
